1   /************************************************************
2   *                     Copyright                            *
3   * Portions of this software are Copyright (c) 1993 - 2002, *
4   * Chad Z. Hower (Kudzu) and the Indy Pit Crew              *
5   *  - http://www.nevrona.com/Indy/                          *
6   ************************************************************/
7   package org.indy.socks;
8   
9   import org.indy.IndyComponent;
10  
11  import org.indy.io.IOHandler;
12  import org.indy.io.IndyIOException;
13  import org.indy.io.ReadTimedOutException;
14  
15  import org.indy.util.IndyUtilities;
16  
17  
18  /***
19   *  Description of the Class
20   *
21   *@author    owen
22   */
23  public class SocksInfo extends IndyComponent {
24    /***
25   *  Description of the Field
26   */
27    protected Authentication authentication = Authentication.NO_AUTHENTICATION;
28  
29    /***
30   *  Description of the Field
31   */
32    protected String host = null;
33  
34    /***
35   *  Description of the Field
36   */
37    protected int port = 0;
38  
39    /***
40   *  Description of the Field
41   */
42    protected String username = null;
43  
44    /***
45   *  Description of the Field
46   */
47    protected String password = null;
48  
49    /***
50   *  Description of the Field
51   */
52    protected Version version = Version.NOSOCKS;
53  
54    /***
55   *  Description of the Field
56   */
57    protected IOHandler ioHandler = null;
58  
59    /***
60   *  Constructor for the IdSocksInfo object
61   *
62   *@param  soInfo  Description of the Parameter
63   */
64    public SocksInfo(SocksInfo soInfo) {
65      this.authentication = soInfo.authentication;
66      this.host = soInfo.host;
67      this.username = soInfo.username;
68      this.password = soInfo.password;
69      this.port = soInfo.port;
70      this.version = soInfo.version;
71    }
72  
73    /***
74   *  Constructor for the IdSocksInfo object
75   */
76    public SocksInfo() {
77    }
78  
79    /***
80   *  Sets the authentication attribute of the IdSocksInfo object
81   *
82   *@param  newAuthentication  The new authentication value
83   */
84    public void setAuthentication(SocksInfo.Authentication newAuthentication) {
85      authentication = newAuthentication;
86    }
87  
88    /***
89   *  Sets the host attribute of the IdSocksInfo object
90   *
91   *@param  _host  The new host value
92   */
93    public void setHost(String _host) {
94      host = _host;
95    }
96  
97    /***
98   *  Sets the port attribute of the IdSocksInfo object
99   *
100  *@param  _port  The new port value
101  */
102   public void setPort(int _port) {
103     port = _port;
104   }
105 
106   /***
107  *  Sets the username attribute of the IdSocksInfo object
108  *
109  *@param  _username  The new username value
110  */
111   public void setUsername(String _username) {
112     username = _username;
113   }
114 
115   /***
116  *  Sets the password attribute of the IdSocksInfo object
117  *
118  *@param  _password  The new password value
119  */
120   public void setPassword(String _password) {
121     password = _password;
122   }
123 
124   /***
125  *  Sets the socksVersion attribute of the IdSocksInfo object
126  *
127  *@param  _version  The new socksVersion value
128  */
129   public void setSocksVersion(SocksInfo.Version _version) {
130     version = _version;
131   }
132 
133   /***
134  *  Sets the ioHandler attribute of the IdSocksInfo object
135  *
136  *@param  _ioHandler  The new ioHandler value
137  */
138   public void setIoHandler(IOHandler _ioHandler) {
139     ioHandler = _ioHandler;
140   }
141 
142   /***
143  *  Gets the authentication attribute of the IdSocksInfo object
144  *
145  *@return    The authentication value
146  */
147   public SocksInfo.Authentication getAuthentication() {
148     return authentication;
149   }
150 
151   /***
152  *  Gets the host attribute of the IdSocksInfo object
153  *
154  *@return    The host value
155  */
156   public String getHost() {
157     return host;
158   }
159 
160   /***
161  *  Gets the port attribute of the IdSocksInfo object
162  *
163  *@return    The port value
164  */
165   public int getPort() {
166     return port;
167   }
168 
169   /***
170  *  Gets the username attribute of the IdSocksInfo object
171  *
172  *@return    The username value
173  */
174   public String getUsername() {
175     return username;
176   }
177 
178   /***
179  *  Gets the password attribute of the IdSocksInfo object
180  *
181  *@return    The password value
182  */
183   public String getPassword() {
184     return password;
185   }
186 
187   /***
188  *  Gets the socksVersion attribute of the IdSocksInfo object
189  *
190  *@return    The socksVersion value
191  */
192   public Version getSocksVersion() {
193     return version;
194   }
195 
196   /***
197  *  Description of the Method
198  *
199  *@param  host           Description of the Parameter
200  *@param  port           Description of the Parameter
201  *@throws  IdSocksError  Description of the Exception
202  */
203   public void makeSocksConnection(String host, int port)
204                            throws SocksException, ReadTimedOutException {
205     if ((version == Version.SOCKS4) || (version == Version.SOCKS4A)) {
206       makeSocks4Connection(host, port);
207     }
208     else if (version == Version.SOCKS5) {
209       makeSocks5Connection(host, port);
210     }
211   }
212 
213   /***
214  *  Description of the Method
215  *
216  *@param  host           Description of the Parameter
217  *@param  port           Description of the Parameter
218  *@throws  IdSocksError  Description of the Exception
219  */
220   public void makeSocks4Connection(String host, int port)
221                             throws SocksException, ReadTimedOutException {
222     byte[] request = new byte[263];
223 
224     request[0] = 4;
225     request[1] = 1;
226     request[2] = (byte) (port & 0xFF00);
227     request[3] = (byte) (port & 0xFF);
228 
229     int pos = 4;
230 
231     if (version == Version.SOCKS4A) {
232       request[4] = 0;
233       request[5] = 0;
234       request[6] = 0;
235       request[7] = 1;
236     }
237     else {
238       /*** @todo NO java.net call here!! */
239 
240       //probably should delegate java.net call elsewhere
241       try {
242         java.net.InetAddress ia = java.net.InetAddress.getByName(host);
243         byte[] addr = ia.getAddress();
244 
245         request[4] = addr[0];
246         request[5] = addr[1];
247         request[6] = addr[2];
248         request[7] = addr[3];
249       }
250        catch (java.net.UnknownHostException uhe) {
251         //argghh
252         throw new SocksUnknownHostException("Unknown host " + host);
253       }
254     }
255 
256     pos = 8;
257 
258     System.arraycopy(username.getBytes(), 0, request, pos, username.length());
259     pos += username.length();
260     request[pos] = '\000';
261     pos++;
262 
263     if (version == Version.SOCKS4A) {
264       System.arraycopy(host.getBytes(), 0, request, pos, host.length());
265       pos += host.length();
266       request[pos++] = '\000';
267     }
268 
269     byte[] response = new byte[8];
270 
271     try {
272       ioHandler.write(request, 0, 8);
273       ioHandler.read(response, 0, 8);
274     }
275      catch (IndyIOException ioe) {
276       throw new SocksServerRespondException(IndyUtilities.getResourceString(
277                                                 "RSSocksServerRespondError"));
278     }
279 
280     switch (response[1]) {
281       case 90:
282         break;
283 
284       //success, do nothing
285       case 91:
286         throw new SocksRequestFailedException(IndyUtilities.getResourceString(
287                                                   "RSSocksRequestFailed"));
288 
289       case 92:
290         throw new SocksRequestServerFailedException(IndyUtilities.getResourceString(
291                                                         "RSSocksRequestServerFailed"));
292 
293       case 93:
294         throw new SocksRequestIdentFailedException(IndyUtilities.getResourceString(
295                                                        "RSSocksRequestIdentFailed"));
296 
297       default:
298         throw new SocksUnknownException(IndyUtilities.getResourceString(
299                                             "RSSocksUnknownError"));
300     }
301   }
302 
303   /***
304  *  Description of the Method
305  *
306  *@param  host           Description of the Parameter
307  *@param  port           Description of the Parameter
308  *@throws  IdSocksError  Description of the Exception
309  */
310   public void makeSocks5Connection(String host, int port)
311                             throws SocksException, ReadTimedOutException {
312     byte[] tmpBuf = new byte[255];
313 
314     if (authentication == Authentication.NO_AUTHENTICATION) {
315       tmpBuf[2] = 0x0;
316     }
317     else {
318       tmpBuf[2] = 0x2;
319     }
320 
321     byte requestedAuthMethod = tmpBuf[2];
322 
323     tmpBuf[0] = 0x5;
324 
325 
326     // socks version
327     tmpBuf[1] = 0x1;
328 
329     //number of possible authentication methods
330     int len = 2 + tmpBuf[1];
331 
332     try {
333       ioHandler.write(tmpBuf, 0, len);
334       ioHandler.read(tmpBuf, 0, 2);
335     }
336      catch (IndyIOException ioe) {
337       throw new SocksServerRespondException(IndyUtilities.getResourceString(
338                                                 "RSSocksServerRespondError"));
339     }
340 
341     byte serverAuthMethod = tmpBuf[1];
342 
343     if ((serverAuthMethod != requestedAuthMethod) || 
344           (serverAuthMethod == 0xFF)) {
345       throw new SocksAuthMethodException(IndyUtilities.getResourceString(
346                                              "RSSocksAuthMethodError"));
347     }
348 
349     if (authentication == Authentication.USERNAME_PASSWORD) {
350       if ((username == null) || (password == null)) {
351         //throw  exception ??
352       }
353 
354       tmpBuf[0] = 0x1;
355 
356       //length of subnegotiation;
357       int ulen = (username == null) ? 0 : username.length();
358 
359       tmpBuf[1] = (byte) ulen;
360 
361       int pos = 2;
362 
363       if ((ulen > 0) && (username != null)) {
364         System.arraycopy(username.getBytes(), 0, tmpBuf, pos, ulen);
365       }
366 
367       pos += ulen;
368 
369       int passlen = (password == null) ? 0 : password.length();
370 
371       tmpBuf[pos] = (byte) passlen;
372       pos++;
373 
374       if ((passlen > 0) && (password != null)) {
375         System.arraycopy(password.getBytes(), 0, tmpBuf, pos, passlen);
376       }
377 
378       pos += passlen;
379 
380       try {
381         ioHandler.write(tmpBuf, 0, pos);
382 
383 
384         //send the username and password
385         ioHandler.read(tmpBuf, 0, 2);
386       }
387        catch (IndyIOException ioe) {
388         throw new SocksServerRespondException(IndyUtilities.getResourceString(
389                                                   "RSSocksServerRespondError"));
390       }
391 
392       if (tmpBuf[1] != 0x0) {
393         throw new SocksAuthException(IndyUtilities.getResourceString(
394                                          "RSSocksAuthError"));
395       }
396     }
397 
398 
399     //Connection process
400     tmpBuf[0] = 0x5;
401 
402 
403     //socks version
404     tmpBuf[1] = 0x1;
405 
406 
407     //connect method
408     tmpBuf[2] = 0x0;
409 
410 
411     //reserved
412     tmpBuf[3] = 0x3;
413 
414 
415     //Domain name - must find out out about all this
416     //address type: IP v4 Address 0x1
417     //              Domain name   0x3
418     //              IP v6 Address 0x4
419     tmpBuf[4] = (byte) host.length();
420 
421     int pos = 5;
422 
423     if (host.length() > 0) {
424       System.arraycopy(host.getBytes(), 0, tmpBuf, pos, host.length());
425     }
426 
427     pos += host.length();
428 
429 
430     //port
431     tmpBuf[pos] = (byte) (port & 0xFF00);
432     tmpBuf[pos++] = (byte) (port & 0xFF);
433     pos++;
434 
435     try {
436       //send the connection packet
437       ioHandler.write(tmpBuf, 0, pos);
438 
439 
440       // Socks server replies on connect, this is the first part
441       ioHandler.read(tmpBuf, 0, 5);
442     }
443      catch (IndyIOException ioe) {
444       throw new SocksServerRespondException(IndyUtilities.getResourceString(
445                                                 "RSSocksServerRespondError"));
446     }
447 
448     switch (tmpBuf[1]) {
449       case 0:
450         break;
451 
452       //success  - do nothing
453       case 1:
454         throw new SocksServerGeneralException(IndyUtilities.getResourceString(
455                                                   "RSSocksServerGeneralError"));
456 
457       case 2:
458         throw new SocksServerPermissionException(IndyUtilities.getResourceString(
459                                                      "RSSocksServerPermissionError"));
460 
461       case 3:
462         throw new SocksServerNetUnreachableException(IndyUtilities.getResourceString(
463                                                          "RSSocksServerNetUnreachableError"));
464 
465       case 4:
466         throw new SocksServerHostUnreachableException(IndyUtilities.getResourceString(
467                                                           "RSSocksServerHostUnreachableError"));
468 
469       case 5:
470         throw new SocksServerConnectionRefusedException(IndyUtilities.getResourceString(
471                                                             "RSSocksServerConnectionRefusedError"));
472 
473       case 6:
474         throw new SocksServerTTLExpiredException(IndyUtilities.getResourceString(
475                                                      "RSSocksServerTTLExpiredError"));
476 
477       case 7:
478         throw new SocksServerCommandException(IndyUtilities.getResourceString(
479                                                   "RSSocksServerCommandError"));
480 
481       case 8:
482         throw new SocksServerAddressException(IndyUtilities.getResourceString(
483                                                   "RSSocksServerAddressError"));
484 
485       default:
486         throw new SocksUnknownException(IndyUtilities.getResourceString(
487                                             "RSSocksUnknownError"));
488     }
489 
490     //type of destination address is domain name
491     switch (tmpBuf[3]) {
492       //IPv4
493       case 1:
494         len = 4 + 2;
495 
496         break;
497 
498       // 4 is for address and 2 is for port length
499       //FQDN
500       case 3:
501         len = tmpBuf[4] + 2;
502 
503         break;
504 
505       // 2 is for port length
506       //IPv6
507       case 4:
508         len = 16 + 2;
509 
510       // 16 is for address and 2 is for port length
511     }
512 
513     try {
514       // Socks server replies on connect, this is the second part
515       ioHandler.read(tmpBuf, 0, len - 1);
516 
517       //
518     }
519      catch (IndyIOException ioe) {
520       throw new SocksServerRespondException(IndyUtilities.getResourceString(
521                                                 "RSSocksServerRespondError"));
522     }
523   }
524 
525   /***
526  *  Description of the Class
527  *
528  *@author    owen
529  */
530   public final static class Version {
531     /***
532  *  Description of the Field
533  */
534     public final static Version NOSOCKS = new Version("No SOCKS");
535 
536     /***
537  *  Description of the Field
538  */
539     public final static Version SOCKS4 = new Version("SOCKS 4");
540 
541     /***
542  *  Description of the Field
543  */
544     public final static Version SOCKS4A = new Version("SOCKS 4A");
545 
546     /***
547  *  Description of the Field
548  */
549     public final static Version SOCKS5 = new Version("SOCKS 5");
550     private final String _desc;
551 
552     private Version(String desc) {
553       _desc = desc;
554     }
555 
556     /***
557  *  Description of the Method
558  *
559  *@return    Description of the Return Value
560  */
561     public String toString() {
562       return "SOCKS Version: " + _desc;
563     }
564   }
565 
566   /***
567  *  Description of the Class
568  *
569  *@author    owen
570  */
571   public final static class Authentication {
572     /***
573  *  Description of the Field
574  */
575     public final static Authentication NO_AUTHENTICATION = 
576         new Authentication("None");
577 
578     /***
579  *  Description of the Field
580  */
581     public final static Authentication USERNAME_PASSWORD = 
582         new Authentication("Username-Password");
583     private String _desc;
584 
585     private Authentication(String desc) {
586       _desc = desc;
587     }
588 
589     /***
590  *  Description of the Method
591  *
592  *@return    Description of the Return Value
593  */
594     public String toString() {
595       return "SOCKS Authentication: " + _desc;
596     }
597   }
598 }
This page was automatically generated by Maven